/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package evocarcassonne.core.generator;

import evocarcassonne.core.utils.Card;
import evocarcassonne.core.utils.Rand;
import evocarcassonne.core.utils.ZoneType;
import java.util.ArrayList;
import java.util.List;

/**
 *
 * @author nobpn
 */
public class TilePattern {

    ZoneType type;
    boolean deadEnd = false;
    List<Integer> deadEnds;
    int touch = -1;
    List<Integer> linkedMainZones;
    List<List<Integer>> linkedFieldsZones;
    int rotation;

    public TilePattern() {
        linkedMainZones = new ArrayList();
        deadEnds = new ArrayList();
        linkedFieldsZones = new ArrayList();
    }

    private TilePattern(TilePattern tp) {
        this();
        type = tp.type;
        rotation = tp.rotation;
        touch = tp.touch;
        deadEnd = tp.deadEnd;
//        deadEnds = tp.deadEnds;
    }

    static TilePattern simpleElt(int rot) {

        int scenario = Rand.getInt(3);

//        System.out.println("scenario:"+scenario);
//        scenario = 1;

        switch (scenario) {

            case 0:
                // Simple Double Simple
                return simpleCity(rot);
//                break;

            case 1:
                // Simple Triple
                return simpleDeadEndRoad(rot);

//                break;
            default:
                return simpleCity(rot);

        }

//        return simpleRoad(rot);


    }

    private static TilePattern simpleCity(int rot) {

        TilePattern tp = new TilePattern();

        tp.type = ZoneType.CITY;
        tp.rotation = rot;

        tp.linkedMainZones.add(Card.N);

        tp = rotate(tp);

        return tp;
    }

    private static TilePattern simpleDeadEndRoad(int rot) {

        TilePattern tp = new TilePattern();

        tp.type = ZoneType.ROAD;
        tp.rotation = rot;

        tp.linkedMainZones.add(Card.N);

        tp.deadEnd = true;
        tp.deadEnds.add(Card.N);

        tp = rotate(tp);

        return tp;
    }

    public static TilePattern doubleElt(int rot) {

        int scenario = Rand.getInt(2);

//        System.out.println("scenario:"+scenario);
        scenario = 0;

        switch (scenario) {

            case 0:
                // Simple Double Simple
                return doubleRoad(rot);
//                break;

            case 1:
                // Simple Triple
                return doubleCity(rot);

            case 2:
                // Simple Triple
                return touchCity(rot, Card.E);
//                break;
            default:
                return doubleCity(rot);

        }



    }

    private static TilePattern touchCity(int rot, int touchZone) {
        TilePattern tp = new TilePattern();

        tp.type = ZoneType.ROAD;
        tp.rotation = rot;

        // link ROAD
        tp.linkedMainZones.add(Card.E);
        tp.linkedMainZones.add(Card.S);

        //link smallFields
        List<Integer> smallfield = new ArrayList();
        smallfield.add(Card.ESE);
        smallfield.add(Card.SSE);

        tp.linkedFieldsZones.add(smallfield);

        tp = rotate(tp);

        return tp;
    }

    private static TilePattern doubleCity(int rot) {
        TilePattern tp = new TilePattern();

        tp.type = ZoneType.CITY;
        tp.rotation = rot;

        tp.linkedMainZones.add(Card.S);
        tp.linkedMainZones.add(Card.E);


        tp = rotate(tp);

        return tp;
    }

    private static TilePattern doubleRoad(int rot) {
        TilePattern tp = new TilePattern();

        tp.type = ZoneType.ROAD;
        tp.rotation = rot;

        // link ROAD
        tp.linkedMainZones.add(Card.E);
        tp.linkedMainZones.add(Card.S);

        //link smallFields
        List<Integer> smallfield = new ArrayList();
        smallfield.add(Card.ESE);
        smallfield.add(Card.SSE);

        tp.linkedFieldsZones.add(smallfield);

        tp = rotate(tp);

        return tp;
    }

    public static TilePattern tripleElt(int rot) {
        return tripleRoad(rot);
    }

    private static TilePattern tripleCity(int rot) {
        TilePattern tp = new TilePattern();

        tp.rotation = rot;
        tp.type = ZoneType.CITY;

        tp.linkedMainZones.add(Card.S);
        tp.linkedMainZones.add(Card.E);
        tp.linkedMainZones.add(Card.W);

        tp = rotate(tp);


        return tp;
    }

    private static TilePattern tripleRoad(int rot) {
        TilePattern tp = new TilePattern();

        tp.type = ZoneType.ROAD;
        tp.rotation = rot;

        // link ROAD
        tp.linkedMainZones.add(Card.E);
        tp.linkedMainZones.add(Card.S);
        tp.linkedMainZones.add(Card.W);

        //link smallFields
        List<Integer> smallfield1 = new ArrayList();
        smallfield1.add(Card.ESE);
        smallfield1.add(Card.SSE);

        tp.linkedFieldsZones.add(smallfield1);

        //link smallFields
        List<Integer> smallfield2 = new ArrayList();
        smallfield2.add(Card.SSW);
        smallfield2.add(Card.WSW);

        tp.linkedFieldsZones.add(smallfield2);


        tp = rotate(tp);

        return tp;
    }

    private static TilePattern rotate(TilePattern tp) {

        TilePattern rpt = new TilePattern(tp);

        for (Integer oldCard : tp.linkedMainZones) {
//        zones[(card - tp.rotation + zones.length) % zones.length];
            int newCard = (oldCard - tp.rotation + 12) % 12;
            rpt.linkedMainZones.add(newCard);
        }

        if (tp.type == ZoneType.ROAD) {
            if (tp.deadEnd) {

                for (Integer oldCard : tp.deadEnds) {
                    int newCard = (oldCard - tp.rotation + 12) % 12;
                    rpt.deadEnds.add(newCard);
                }
            } else if (tp.touch != -1) {
            } else {

                for (List smallField : tp.linkedFieldsZones) {

                    List<Integer> newSmallField = new ArrayList();

                    for (Object object : smallField) {

                        Integer oldCard = (Integer) object;

                        int newCard = (oldCard - tp.rotation + 12) % 12;
                        newSmallField.add(newCard);
                    }
                    rpt.linkedFieldsZones.add(newSmallField);
                }

//                for (Integer oldCard : tp.linkedFieldsZones) {
////        zones[(card - tp.rotation + zones.length) % zones.length];
//                    int newCard = (oldCard - tp.rotation + 12) % 12;
//                    rpt.linkedFieldsZones.add(newCard);
//                }

            }
        }



        return rpt;
    }
}
